import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flash.utils.Timer;

import haxe.FastList;
import haxe.Timer;

import nme.Assets;
import TileModel;
import HealthBarView;
import BaseLevel;
import Kongregate;

import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

class CircleCollisionLevel extends BaseLevel
{
  
  private var _pinkMap:Array<Array<Int>>;  
  private static inline var MAX_TILE_SIZE:Int = 64;
  private static inline var MAP_COLUMNS:Int = 19;
  private static inline var MAP_ROWS:Int = 8;
  
  //tile ID s in tile sheet
  private static inline var BOX:Int = 00;
  private static inline var SKY:Int = 10;
  private static inline var PLATFORM:Int = 11;
  private static inline var MACHINE_GUN:Int = 01;
  private static inline var PISTOL:Int = 02;
  private static inline var SHOTGUN:Int = 03;
  private static inline var DOOR:Int = 13;

  private static inline var PINK:Int = 21;
  private static inline var BLUE:Int = 20;

  private static inline var PinkRadius:Float = 20.5;
  private static inline var BlueRadius:Float = 20.5;
  public var _CircleModel:CircleModel;
  public var _CircleView:PlayerCircleView;
  public var _CircleController:CircleController;
  public var _c1:CircleModel;
  public var _c1_View:CircleView;
  public var _c2:CircleModel;
  public var _c2_View:CircleView;
  public var _c3:CircleModel;
  public var _c3_View:CircleView;
  public var _c4:CircleModel;
  public var _c4_View:CircleView;
  public var _c5:CircleModel;
  public var _c5_View:CircleView;
  public var _VectorModel:VectorModel;
  public var _VectorView:VectorView;
  private var _SpriteLayer:Sprite;
  public var  WelcomeText:TextField;
  public var  CircleExplationText:TextField;
  public var  CircleForumlaText:TextField;
  public var  CircleSizeText:TextField;

  public function new(stage:Dynamic){
  super(stage);
  MAP_COLUMNS = 26;
    removeChild(_staticBackgroundBitmap);
    removeChild(_backgroundBitmap);
    removeChild(_foregroundBitmap);
  _staticBackgroundBitmapData = Assets.getBitmapData("Cardboard_Background.png");
  _staticBackgroundBitmap = new Bitmap(_staticBackgroundBitmapData);

  _backgroundBitmapData = new BitmapData(MAP_COLUMNS * MAX_TILE_SIZE, 
          MAP_ROWS * MAX_TILE_SIZE, true, 0);
  _backgroundBitmap = new Bitmap(_backgroundBitmapData);

  _foregroundBitmapData = new BitmapData(MAP_COLUMNS * MAX_TILE_SIZE, 
          MAP_ROWS * MAX_TILE_SIZE, true, 0);
  _foregroundBitmap = new Bitmap(_foregroundBitmapData);

  _SpriteLayer = new Sprite();
  _SpriteLayer.graphics.beginFill(0x0000000,0);
  _SpriteLayer.graphics.drawRect(0,0,MAP_COLUMNS * MAX_TILE_SIZE,MAP_ROWS * MAX_TILE_SIZE);
  _SpriteLayer.visible = true;

  _camera = new Rectangle (0, 0, stage.stageWidth, stage.stageHeight);

    addChild(_staticBackgroundBitmap);
    addChild(_backgroundBitmap);
    addChild(_foregroundBitmap);
    addChild(_SpriteLayer);
  _platformMap = 
	[
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM]
	];
  _gameObjectMap = 
	[
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,DOOR,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,DOOR,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	  ]  ;


  buildReserveEnemies();


  // myTimer = new Timer(12);
  //   myTimer.addEventListener("timer", OnEnter);
  //   myTimer.start();
  //Add the game bitmaps
			  
			  //Run the buildMap method to convert the
			  //map array data into a visual display
			  

      
    CircleExplationText = new TextField();
    CircleExplationText.htmlText = "<font size ='16'>In order to calculate if a two circles have collied you merely need to Calculate the distance between the two centers.\n\nIf this distance is less than than the combined radius of the two circles than they have collided.</font>";
    CircleExplationText.x = 150;CircleExplationText.y = 5;
    CircleExplationText.width = 200; CircleExplationText.height = 170;
    CircleExplationText.wordWrap = true;
    CircleExplationText.border = true;
    _SpriteLayer.addChild(CircleExplationText);

    CircleForumlaText = new TextField();
    CircleForumlaText.width = 400; CircleForumlaText.height = 180;
    CircleForumlaText.htmlText = "<font size ='16'>//_c1 is circle 1 _c2 circle 2\nvar m = Math.sqrt(Math.pow(_c1.xPos -_c2.xPos,2) +\nMath.pow( _c1.yPos - _c2.yPos,2));\n   totalRadii = _c1.radius + _c2.radius; \nif(m &lt; totalRadii)\n{\n  //collision has occurred.\n}</font>";
    CircleForumlaText.x = 500;CircleForumlaText.y = 150;

    CircleForumlaText.wordWrap = true;
    CircleForumlaText.border = true;
    _SpriteLayer.addChild(CircleForumlaText);


    CircleSizeText = new TextField();
    CircleSizeText.width = 150; CircleSizeText.height = 180;
    CircleSizeText.htmlText = "<font size ='16'>This logic can be Extended to circles of different size, including a point (a circle with the radius of 0).</font>";
    CircleSizeText.x = 1200;CircleSizeText.y = 50;

    CircleSizeText.wordWrap = true;
    CircleSizeText.border = true;
    _SpriteLayer.addChild(CircleSizeText);
    }
public override function Load(inVolume:Bool,inSound:Bool,inKongVar:CKongregate,inDifficulty:Int)
{
 super.Load(inVolume,inSound,inKongVar,inDifficulty);
 buildMap(_platformMap);
 buildMap(_gameObjectMap);
 _CircleModel = new CircleModel("main");
_CircleModel.setX = 64*3.5;_CircleModel.setY = 384;
  _CircleController = new CircleController(_CircleModel);
 _CircleView = new PlayerCircleView(_CircleModel,_CircleController,stage);

  _SpriteLayer.addChild(_CircleView);

  _c1 = new CircleModel("Secondary");
  _c1_View = new CircleView(_c1);
  _SpriteLayer.addChild(_c1_View);
  _c1.xPos = 576;_c1.yPos = 384;
  
  _VectorModel = new VectorModel(_CircleModel.xPos,_CircleModel.yPos, _c1.xPos,_c1.yPos);
  _VectorView = new VectorView(_VectorModel,new Rectangle(0,0,0,0),1);
  _SpriteLayer.addChild(_VectorView);

  _c2 = new CircleModel("Secondary",40);
  _c2_View = new CircleView(_c2);
  _SpriteLayer.addChild(_c2_View);
  _c2.setX = 1280;_c2.setY = 384;

  _c3 = new CircleModel("Secondary",1);
  _c3_View = new CircleView(_c3);
  _SpriteLayer.addChild(_c3_View);
  _c3.setX = 1380;_c3.setY = 320;

  _c4 = new CircleModel("Secondary",1);
  _c4_View = new CircleView(_c4);
  _SpriteLayer.addChild(_c4_View);
  _c4.setX = 1234;_c4.setY = 167;

  _c5 = new CircleModel("Secondary",15);
  _c5_View = new CircleView(_c5);
  _SpriteLayer.addChild(_c5_View);
  _c5.setX = 1485;_c5.setY = 200;
  
}

public override function checkWin():Bool
{
  if(!_CircleModel.exit)
    {return false;}
  var Door1 = new SquareModel();
  Door1.xPos = 1*64;
  Door1.yPos = 6*64;
  Door1.width = 64;
  Door1.height = 64;
  var boxSquare = new SquareModel();
  boxSquare.xPos = _CircleModel.xPos-_CircleModel.width/2;
  boxSquare.yPos = _CircleModel.yPos-_CircleModel.height/2;
  boxSquare.width = _CircleModel.width;
  boxSquare.height = _CircleModel.height;
  if(_collisionController.squareModelCollision(Door1,boxSquare))
  {
    return true;
  }
    var Door2 = new SquareModel();
  Door2.xPos = 23*64;
  Door2.yPos = 6*64;
  Door2.width = 64;
  Door2.height = 64;
  if(_collisionController.squareModelCollision(Door2,boxSquare))
  {
    return true;
  }
  return  false;
}

  public  override function UnLoad()
  {
   _SpriteLayer.removeChild(_CircleView);
   _SpriteLayer.removeChild(_c1_View);
   if(_SpriteLayer.contains(_VectorView))
   {
    _SpriteLayer.removeChild(_VectorView);
   }
   _SpriteLayer.removeChild(_c2_View);
   _SpriteLayer.removeChild(_c3_View);
   _SpriteLayer.removeChild(_c4_View);
   _SpriteLayer.removeChild(_c5_View);
      super.UnLoad();
      //_MainCharacterController = null;

  }
public function checkCollisionCircle(_c1:CircleModel,_c2:CircleModel,totalRadii:Float,view:CircleView)
{
	var m = Math.sqrt(Math.pow(_c1.xPos -_c2.xPos,2) +
		  Math.pow( _c1.yPos - _c2.yPos,2));   
	if(m < totalRadii)
	{
	  view.hit();
	}
	else
	{
	  view.unHit();
	}
}
override function OnEnter(e:flash.events.Event)
{
    try
    {
      if(checkWin())
      {	
	_CircleModel.exit = false;
	UnLoad();
	this.removeEventListener(Event.ENTER_FRAME, OnEnter);
	dispatchEvent(new Event("LevelFinished"));return;
      }
      _CircleModel.exit = false;
      if(Pause == "Paused")
      {
	return;
      }	

      var VectorAdded = _SpriteLayer.contains(_VectorView);
      if(_CircleModel.xPos > 1088)
      {
	if(VectorAdded)
	{
	  _SpriteLayer.removeChild(_VectorView);
	}
	checkCollisionCircle(_CircleModel, _c2,_CircleModel.radius+_c2.radius,_c2_View);
	//_c3 and _c4 have no radius.
	checkCollisionCircle(_CircleModel, _c3,_CircleModel.radius,_c3_View);
	checkCollisionCircle(_CircleModel, _c4,_CircleModel.radius,_c4_View);

	checkCollisionCircle(_CircleModel, _c5,_CircleModel.radius+_c5.radius,_c5_View);
      }
      else
      {
	var m = Math.sqrt(Math.pow(_c1.xPos -_CircleModel.xPos,2) +
		  Math.pow( _c1.yPos - _CircleModel.yPos,2));   
	var totalRadii = _c1.radius + _CircleModel.radius; 
	if(m < totalRadii)
	{
	  _c1_View.hit();
	}
	else
	{
	  _c1_View.unHit();
	}
	if(!VectorAdded)
	{
	  _SpriteLayer.addChild(_VectorView);
	}
      }
	
      
      //Clear the stage bitmap from the previous frame so that it's
      //blank when you add the new tile positions
      _foregroundBitmapData.fillRect(_foregroundBitmapData.rect, 0);
      //Set up the camera to focus on the cat
      _camera.x = _CircleModel.xPos-Constants.flashWidth*0.5;
      _camera.y = 0;
      
      //Check the camera's game world boundaries
      //Left
      if(_camera.x < 0)
      {
	_camera.x = 0;
      }
      
      //Right
      if(_camera.x > (MAP_COLUMNS * MAX_TILE_SIZE) 
	- Constants.flashWidth)
      {
	_camera.x = (MAP_COLUMNS * MAX_TILE_SIZE) - Constants.flashWidth;
      }
      
      //Bottom
      if(_camera.y > (MAP_ROWS * MAX_TILE_SIZE) - Constants.flashHeight)
      {
	_camera.y = (MAP_ROWS * MAX_TILE_SIZE) - Constants.flashHeight;
      }
      
      //Top
      if(_camera.y < 0)
      {
	_camera.y = 0;
      }
    
      //Update the box's Model
      _CircleModel.update();
  _VectorModel.update(_CircleModel.xPos,_CircleModel.yPos, _c1.xPos,_c1.yPos);
      //if Shoting
//       shotVector.update(0, 0,0,0);
//       	var y2 =  _CircleModel.yPos + _CircleModel.height/2;
// 	var y1 = mouseY;
// 	
// 	var x2 = _CircleModel.xPos +_CircleModel.width/2;
// 	var x1 = mouseX+_camera.x;
// 	var m = (y2 - y1 )/(x2 - x1);
// 	var b = (y2) - m*(x2);
// 	var testVector = new VectorModel();
// 	testVector.update(x2, y2,x1,y1);

    _collisionMap = [[]];
    for(row in 0...MAP_ROWS)
    {
      _collisionMap[row] = [];
      for(column in 0...MAP_ROWS)	
      {
	_collisionMap[row][column] = new List<TileModel>();
      }
    }
    for(enemy in _enemies)
    {
	_collisionMap[enemy.model.mapRow][enemy.model.mapColumn].add(enemy.model);
	enemy.model.update();
      if (enemy.model.xPos + (enemy.model.width) > maxX)
      {
	enemy.model.setX = maxX - (enemy.model.width);
	enemy.model.vx = 0;
      }
      else if (enemy.model.xPos < minX)
      {
	      enemy.model.setX = minX;
	      enemy.model.vx = 0;
      }
      if (enemy.model.yPos < 0)
      {
	      enemy.model.setY = 0;
	      enemy.model.vy = 0;
      }

      else if (enemy.model.yPos + enemy.model.height > Constants.flashHeight && enemy.model.vy > 0)
      {
	      enemy.model.setY = Constants.flashHeight - enemy.model.height;
	      enemy.model.vy = 0;
      } 
	drawGameObject(enemy.model,_foregroundBitmapData);
    }
// 	for(column in -1...2)
// 	{
// 	  for(row in -1...2)
// 	  {
// 	    if(_CircleModel.mapRow + row < _collisionMap.length &&
// 	       _CircleModel.mapRow + row >= 0 &&
// 	       _CircleModel.mapColumn + column < _collisionMap[0].length &&
// 	       _CircleModel.mapColumn + column >= 0)
// 	    {		
// 	      	for(model in _collisionMap[_CircleModel.mapRow + row ][_CircleModel.mapColumn + column])
// 		{
// 		  //collision
// 		}
// 	    }
// 	  }
// 	}
      //Stop the box at the stage boundaries
      //StageBoundaries.stopBitmap(_CircleModel, stage);
      maxX = MAP_COLUMNS * MAX_TILE_SIZE;
      if (_CircleModel.xPos + (_CircleModel.width/2) > maxX)
      {
	_CircleModel.setX = maxX - (_CircleModel.width/2);
	_CircleModel.vx = 0;
      }
      else if (_CircleModel.xPos-(_CircleModel.width/2) < minX)
      {
	      _CircleModel.setX = minX+(_CircleModel.width/2);
	      _CircleModel.vx = 0;
      }
      if (_CircleModel.yPos - _CircleModel.height/2 < 0)
      {
	      _CircleModel.setY =  _CircleModel.height/2;
	      _CircleModel.vy = 0;
      }
      else if (_CircleModel.yPos + _CircleModel.height/2 > Constants.flashHeight && _CircleModel.vy > 0)
      {
	      _CircleModel.setY = Constants.flashHeight - _CircleModel.height/2;
	      _CircleModel.vy = 0;
      } 
      
 
    _collisionController.platformCollisionCircleModel(_CircleModel,_platformMap,MAX_TILE_SIZE,PLATFORM);
      //Check for collisions with the platforms
//       _collisionController.platformCollision
// 	(_CircleModel, _platformMap, MAX_TILE_SIZE, PLATFORM);

      //Blit the box on the foreground bitmap

      //Scroll the game world
      _foregroundBitmap.scrollRect = _camera;
      _backgroundBitmap.scrollRect = _camera;
      _SpriteLayer.scrollRect = _camera;

      //_gunView.scrollRect = _camera;
      //drawGunObject(_gunModel,_currentGunBitmapData, _foregroundBitmapData); 
    }
catch(err:Dynamic)
    {
    trace(err.message);
    }
}

  public override function buildReserveEnemies()
  {
  }
}